
#include <QFileDialog>
#include <QMessageBox>
#include <QApplication>
#include <QAction>
#include <QMenuBar>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QDebug>

#include "mainwindow.h"
#include "filestream.h"
#include "searchdialog.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setAcceptDrops(true);
    init();
    setTitle("");
    m_dllPath = "";
    openDllFile();
}

MainWindow::~MainWindow()
{
}

void MainWindow::loadFile(const QString &fileName)
{
    statusBar()->showMessage(tr("File loaded"));
    bool ret = m_fileTree->setFile(fileName, m_dllPath);
    qDebug() << __func__ << ret << Qt::endl;
    setTitle(fileName);
}

/* Private Slots */

void MainWindow::open()
{
    if (m_dllPath.isEmpty()) openDllFile();
    if (m_dllPath.isEmpty()) return;

    QString title = tr("Open file");
    QString dir = "..";
    QString filter = FileStream::getSupportFileFilter(m_dllPath);
    QString fileName = QFileDialog::getOpenFileName(this, title, dir, filter);
    if (!fileName.isEmpty()) {
        loadFile(fileName);
    }
}

void MainWindow::close()
{
    setTitle("");
    m_fileTree->closeFile();
}

void MainWindow::openDllFile()
{
    QString title = tr("Chose a library file");
    QString dir = "../lib";
    QString filter = tr("Dll Files(*.dll)");
    QString fileName = QFileDialog::getOpenFileName(this, title, dir, filter);
    if (!fileName.isEmpty()) {
        m_dllPath = fileName;
        statusBar()->showMessage(tr("Library file ready"));
    }
}

void MainWindow::showSearchDialog()
{
    SearchDialog dlg(this);
    if (dlg.exec() == QDialog::Accepted) {
        m_fileTree->setFindBytes(dlg.getSearchBytes());
        m_fileTree->findNext();
    }
}

void MainWindow::showOptionsDialog()
{
}

void MainWindow::about()
{
   QMessageBox::about(this, tr("About FileTreeViewer"),
                      tr("The FileTreeViewer was made by zhyulo."));
}

void MainWindow::selectChanged(int pos, int len)
{
    lbAddress->setText(QString("%1H").arg(pos, 4, 16, QChar('0')).toUpper());
    lbSize->setText(QString("%1").arg(len));
}

/* Private Methods */

void MainWindow::init()
{
    // qDebug() << __func__ << "() in" << Qt::endl;
    //setAttribute(Qt::WA_DeleteOnClose);

    m_fileTree = new FileTree(this);
    setCentralWidget(m_fileTree);

    createActions();
    createMenus();
    createStatusBar();
    // qDebug() << __func__ << "() out" << Qt::endl;
}

void MainWindow::createActions()
{
    m_openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
    m_openAct->setShortcuts(QKeySequence::Open);
    m_openAct->setStatusTip(tr("Open an existing file"));
    connect(m_openAct, SIGNAL(triggered()), this, SLOT(open()));

    m_closeAct = new QAction(tr("&Close"), this);
    m_closeAct->setShortcuts(QKeySequence::Close);
    m_closeAct->setStatusTip(tr("Close the opened file"));
    connect(m_closeAct, SIGNAL(triggered()), this, SLOT(close()));

    m_dllAct = new QAction(tr("&Lib chose..."), this);
    m_dllAct->setStatusTip(tr("Chose a library file to pause data"));
    connect(m_dllAct, SIGNAL(triggered()), this, SLOT(openDllFile()));

    m_exitAct = new QAction(tr("E&xit"), this);
    m_exitAct->setShortcuts(QKeySequence::Quit);
    m_exitAct->setStatusTip(tr("Exit the application"));
    connect(m_exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));

    m_copyAct = new QAction(tr("&Copy"), this);
    m_copyAct->setShortcuts(QKeySequence::Copy);
    m_copyAct->setStatusTip(tr("Copy to Clipboard"));
    connect(m_copyAct, SIGNAL(triggered()), m_fileTree, SLOT(copy()));

    m_findAct = new QAction(QIcon(":/images/find.png"), tr("&Find..."), this);
    m_findAct->setShortcuts(QKeySequence::Find);
    m_findAct->setStatusTip(tr("Show the Dialog for finding and replacing"));
    connect(m_findAct, SIGNAL(triggered()), this, SLOT(showSearchDialog()));

    m_findNextAct = new QAction(tr("Find &next"), this);
    m_findNextAct->setShortcuts(QKeySequence::FindNext);
    m_findNextAct->setStatusTip(tr("Find next occurrence of the searched pattern"));
    connect(m_findNextAct, SIGNAL(triggered()), m_fileTree, SLOT(findNext()));

    m_findLastAct = new QAction(tr("Find &previous"), this);
    m_findLastAct->setShortcuts(QKeySequence::FindPrevious);
    m_findLastAct->setStatusTip(tr("Find previous occurrence of the searched pattern"));
    connect(m_findLastAct, SIGNAL(triggered()), m_fileTree, SLOT(findLast()));

    m_optionsAct = new QAction(tr("&Options"), this);
    m_optionsAct->setStatusTip(tr("Show the Dialog to select applications options"));
    connect(m_optionsAct, SIGNAL(triggered()), this, SLOT(showOptionsDialog()));

    m_aboutAct = new QAction(tr("&About"), this);
    m_aboutAct->setStatusTip(tr("Show the application's About box"));
    connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about()));

    m_aboutQtAct = new QAction(tr("About &Qt"), this);
    m_aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
    connect(m_aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}

void MainWindow::createMenus()
{
    m_fileMenu = menuBar()->addMenu(tr("&File"));
    m_fileMenu->addAction(m_openAct);
    m_fileMenu->addAction(m_closeAct);
    m_fileMenu->addAction(m_dllAct);
    m_fileMenu->addSeparator();
    m_fileMenu->addAction(m_exitAct);

    m_editMenu = menuBar()->addMenu(tr("&Edit"));
    m_editMenu->addAction(m_copyAct);
    m_editMenu->addSeparator();
    m_editMenu->addAction(m_findAct);
    m_editMenu->addAction(m_findNextAct);
    m_editMenu->addAction(m_findLastAct);
    m_editMenu->addSeparator();
    m_editMenu->addAction(m_optionsAct);

    m_helpMenu = menuBar()->addMenu(tr("&Help"));
    m_helpMenu->addAction(m_aboutAct);
    m_helpMenu->addAction(m_aboutQtAct);
}

void MainWindow::createStatusBar()
{
    // Address Label
    QLabel *addressName = new QLabel();
    addressName->setText(tr("Address:"));
    statusBar()->addPermanentWidget(addressName);
    lbAddress = new QLabel();
    lbAddress->setFrameShape(QFrame::Panel);
    lbAddress->setFrameShadow(QFrame::Sunken);
    lbAddress->setMinimumWidth(70);
    statusBar()->addPermanentWidget(lbAddress);

    // Size Label
    QLabel *sizeName = new QLabel();
    sizeName->setText(tr("Size:"));
    statusBar()->addPermanentWidget(sizeName);
    lbSize = new QLabel();
    lbSize->setFrameShape(QFrame::Panel);
    lbSize->setFrameShadow(QFrame::Sunken);
    lbSize->setMinimumWidth(70);
    statusBar()->addPermanentWidget(lbSize);
    connect(m_fileTree, SIGNAL(selectChanged(int, int)), this, SLOT(selectChanged(int, int)));

    statusBar()->showMessage(tr("Ready"));
    connect(m_fileTree, SIGNAL(onMessage(const QString&, int)),
            statusBar(), SLOT(showMessage(const QString&, int)));
}

void MainWindow::setTitle(const QString &fileName)
{
    QString title = "FileTreeViewer";
    if (!fileName.isEmpty()) {
        QString curFile = QFileInfo(fileName).canonicalFilePath();
        title = curFile + " - " + title;
    }
    setWindowFilePath(title);
}
